#include "lex.h"

namespace logo
{

	CodeLine::CodeLine()
	{}

	CodeLine::~CodeLine()
	{}

	CodeLine::CodeLine(CodeLine& rhs)
	{
		tokens = rhs.tokens;
	}

	CodeLine& CodeLine::operator= (const CodeLine& rhs)
	{
		tokens = rhs.tokens;
		return *this;
	}

	CodeFile::CodeFile()
	{}

	CodeFile::~CodeFile()
	{}

	Ptr<CodeFile> CodeFile::Parse(const std::wstring& input, List<LexError>& errors)
	{
		List<std::wstring>  rules;
		CodeFile* file = new CodeFile();
		rules.add(L"[ |\n]+|[\r\n]+");
		rules.add(L"/d+|/d+./d+");
		rules.add(L"/+");
		rules.add(L"-");
		rules.add(L"/*");
		rules.add(L"//");
		rules.add(L">=");
		rules.add(L"<=");
		rules.add(L">");
		rules.add(L"<");
		rules.add(L"==");
		rules.add(L"/(");
		rules.add(L"/)");
		rules.add(L"/[");
		rules.add(L"/]");
		rules.add(L":[A-Z]+");
		rules.add(L"TO|IF|ELSE|REPEAT|END");
		rules.add(L"FD|BK|RT|LT|PU|PD|PE|CS|STOP");
		rules.add(L"[A-Z]+");
		RegexLexer lex(rules);
		List<RegexToken>  tokens;
		tokens = lex.Parse(input).ToList();

		Dictionary<zint, List<RegexToken>> dic;
		auto res=from(tokens).group_by([](RegexToken token){return token.rowStart; });
		for (auto ele : res)
		{
			List<RegexToken>  values;
			for (auto value : ele.second)
			{
				values.add(value);
			}
			dic.add(ele.first, values);
		}

		SortedList<zint> keys=dic.keys();
		for (auto key:keys)
		{
			List<RegexToken> list=dic[key];
			CodeLine line;
			for (auto token:list)
			{
				Token t;
				t.row = token.rowStart + 1;
				t.col = token.columnStart + 1;
				t.value = input.substr(token.start, token.length);
				t.type = (tokentype)token.token;
				if (t.type == tokentype::UNKNOW)
				{
					LexError err;
					err.token = t;
					err.message = L"unknow token";
					errors.add(err);
				}
				else
				{
					line.tokens.add(t);
				}
			}
			file->lines.add(line);
		}
		return file;
	}
};
